package samber

import (
	"fmt"
	"github.com/samber/lo"
)

func ChannelDispatcher() {
	stream := make(chan int, 6)
	stream <- 1
	stream <- 2
	stream <- 3
	stream <- 4
	stream <- 5
	count := 3
	channelBufferCap := 2 // 没buffer也行
	// 看源码自己定义策略 即自己决定写到哪个目标子通道里面
	// 有时候能触发走到这里面 有时候又不行 自己捣鼓下
	var strategy lo.DispatchingStrategy[int] = func(msg int, index uint64, channels []<-chan int) int {
		fmt.Printf("%v %v %v \n", msg, index, channels)
		return msg
	}
	childChan := lo.ChannelDispatcher[int](stream, count, channelBufferCap, strategy)
	fmt.Printf("%v \n", childChan)
}

// Chunk 这个常用 切子数组
func Chunk() {
	list := []int{0, 1, 2, 3, 4}
	result := lo.Chunk(list, 2)
	fmt.Printf("%v \n", result) // [[0 1] [2 3] [4]]
}

func ChunkString() {
	result1 := lo.ChunkString("123456", 2)
	result2 := lo.ChunkString("1234567", 2)
	result3 := lo.ChunkString("", 2)
	result4 := lo.ChunkString("1", 2)

	fmt.Printf("%v\n", result1) // [12 34 56]
	fmt.Printf("%v\n", result2) // [12 34 56 7]
	fmt.Printf("%v\n", result3) // []
	fmt.Printf("%v\n", result4) // [1]
}

// Clamp 在上下届里面在范围里面就是你 否则就取上界/下界
func Clamp() {
	result1 := lo.Clamp(0, -10, 10)
	result2 := lo.Clamp(-42, -10, 10)
	result3 := lo.Clamp(42, -10, 10)

	fmt.Printf("%v\n", result1)
	fmt.Printf("%v\n", result2)
	fmt.Printf("%v\n", result3)
}

// Coalesce 返回第一个非空参数 必须要可比性
func Coalesce() {
	res, ok := lo.Coalesce[int](0, 2, 3)
	fmt.Printf("%v %v \n", res, ok) // 2 true
}

// Compact 返回所有非零元素的切片
func Compact() {
	list := []string{"", "foo", "", "bar", ""}
	result := lo.Compact(list)
	fmt.Printf("%v \n", result) // [foo bar]
}

// Contains 是否存在
func Contains() {
	list := []string{"", "foo", "", "bar", ""}
	contain := lo.Contains(list, "foo")
	fmt.Printf("%v \n", contain) // true
}

// ContainsBy T 在这里是any 可以加上自己逻辑
func ContainsBy() {
	list := []string{"", "foo", "", "bar", ""}
	contain := lo.ContainsBy(list, func(item string) bool {
		if item == "foo" {
			return true
		}
		return false
	})
	fmt.Printf("%v \n", contain) // true
}

func Count() {
	list := []int{0, 1, 2, 3, 4, 5, 0, 1, 2, 3}
	result := lo.Count(list, 2)
	fmt.Printf("%v \n", result) // 2
}

func CountBy() {
	list := []int{0, 1, 2, 3, 4, 5, 0, 1, 2, 3}
	result := lo.CountBy(list, func(i int) bool {
		return i < 4
	})
	fmt.Printf("%v \n", result) // 8
}

// CountValues 计数为Map
func CountValues() {
	result1 := lo.CountValues([]int{})
	result2 := lo.CountValues([]int{1, 2})
	result3 := lo.CountValues([]int{1, 2, 2})
	result4 := lo.CountValues([]string{"foo", "bar", ""})
	result5 := lo.CountValues([]string{"foo", "bar", "bar"})

	/*
		1: map[]
		2: map[1:1 2:1]
		3: map[1:1 2:2]
		4: map[:1 bar:1 foo:1]
		5: map[bar:2 foo:1]
	*/
	fmt.Printf("1: %v\n", result1)
	fmt.Printf("2: %v\n", result2)
	fmt.Printf("3: %v\n", result3)
	fmt.Printf("4: %v\n", result4)
	fmt.Printf("5: %v\n", result5)
}

func CountValuesBy() {
	isEven := func(v int) bool {
		return v%2 == 0
	}
	length := func(v string) int {
		return len(v)
	}

	/*
		1: map[]
		2: map[false:1 true:1]
		3: map[false:1 true:2]
		4: map[0:1 3:2]
		5: map[3:3]
	*/
	result1 := lo.CountValuesBy([]int{}, isEven)
	result2 := lo.CountValuesBy([]int{1, 2}, isEven)
	result3 := lo.CountValuesBy([]int{1, 2, 2}, isEven)
	result4 := lo.CountValuesBy([]string{"foo", "bar", ""}, length)
	result5 := lo.CountValuesBy([]string{"foo", "bar", "bar"}, length)

	fmt.Printf("1: %v\n", result1)
	fmt.Printf("2: %v\n", result2)
	fmt.Printf("3: %v\n", result3)
	fmt.Printf("4: %v\n", result4)
	fmt.Printf("5: %v\n", result5)
}
